package com.geek.gkpush.framework.tomcat.protocol;

import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.net.Nio2Endpoint;
import org.apache.tomcat.util.net.NioEndpoint;
import org.apache.tomcat.util.threads.TaskQueue;
import org.apache.tomcat.util.threads.TaskThreadFactory;
import org.apache.tomcat.util.threads.ThreadPoolExecutor;

import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.TimeUnit;

/**
 * <h1>充分模拟 {@linkplain Nio2Endpoint} 源码逻辑，只是想重写 createExecutor 方法来自定义一个线程池拒绝策略。</h1><br/>
 *
 * <h1><br/><a href="https://u.geekbang.org/subject/arch3/100614201">Java 业务架构实战营：https://u.geekbang.org/subject/arch3/100614201</a></h1><br/><h1><a href="https://gitee.com/ylimhhmily/BizArchPracticeCamp">Java 业务架构实战营代码地址：https://gitee.com/ylimhhmily/BizArchPracticeCamp</a></h1><br/><h1><a href="https://u.geekbang.org/subject/java4th/1001148?source=app_share">高级 Java 工程体系课 2023 版：https://u.geekbang.org/subject/java4th/1001148?source=app_share</a></h1><br/><h1><a href="https://time.geekbang.org/column/intro/100312101?tab=catalog">Dubbo 源码剖析与实战：https://time.geekbang.org/column/intro/100312101?tab=catalog</a></h1>
 *
 * @author hmilyylimh
 * ^_^
 * @version 0.0.1
 * ^_^
 * @date 2023/9/26 21:07
 */
public class CustomNioEndpoint extends NioEndpoint {

    private static final Log log = LogFactory.getLog(CustomNioEndpoint.class);

    @Override
    public void createExecutor() {
        TaskQueue taskqueue = new TaskQueue();
        TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", getDaemon(), getThreadPriority());
        CustomThreadPoolExecutor executor = new CustomThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf, new CustomNioEndpoint.RejectHandler());
        setExecutor(executor);

        // 为了保证和原有的逻辑一摸一样的话，因此这里就需要重新设置 internalExecutor 为 true，保证原滋原味
        internalExecutor = true;
        taskqueue.setParent( (CustomThreadPoolExecutor) executor);
    }

    /**
     * <h1>拒绝策略。</h1><br/>
     *
     * <pre>
     *     注意，调试启动参数：-Dserver.tomcat.max-threads=2 -Dserver.tomcat.max-connections=2 -Dserver.tomcat.accept-count=2 -Dserver.tomcat.min-spare-threads=1
     * </pre>
     *
     * @author hmilyylimh
     *         ^_^
     * @version 0.0.1
     *         ^_^
     * @date 2023/9/27
     *
     */
    private static class RejectHandler implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r,
                                      java.util.concurrent.ThreadPoolExecutor executor) {
            // 先触发告警通知

            // 然后触发 run 方法
            r.run();

            log.error("com.geek.gkpush.framework.tomcat.protocol.CustomNioEndpoint.RejectHandler reject...");
            throw new RejectedExecutionException();
        }
    }
}
